﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using SSRSTestGenerator.Models;
using SSRSTestGenerator.Controllers;
using System.IO;

namespace SSRSTestGenerator.Views
{
    /// <summary>
    /// Interaction logic for NewProjectWindow.xaml
    /// </summary>
    public partial class PropertiesWindow : Window
    {
        #region Class Variables
        private App MainApp { get; set; }
        private SSRSTestGenerator.Models.ClassEnumerations.ApplicationType AppTypeObject { get; set; }
        private ClassEnumerations.ApplicationStatus AppStatus { get; set; }
        private PropsArg TreeNodeData { get; set; }
        private string OriginalReportName { get; set; }     
        #endregion

        #region Delegates
        public delegate void NewPrjProp(object sender, PropsArg arg);
        public event NewPrjProp NewPrjPropEvent;

        public delegate bool CheckDoesClassNameExist(object sender, string className);
        public event CheckDoesClassNameExist CheckedDoesClassNameExist;

        public delegate void NotifyUser(object sender, NotificationArgs arg);
        public event NotifyUser NotifyedUser;
        #endregion

        public PropertiesWindow(SSRSTestGenerator.Models.ClassEnumerations.ApplicationType appType, PropsArg data, SSRSTestGenerator.Models.ClassEnumerations.ApplicationStatus appStatus = ClassEnumerations.ApplicationStatus.New)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;                

                InitializeComponent();

                // ((System.Windows.Navigation.NavigationWindow)LogicalTreeHelper.GetParent(this)).ResizeMode = ResizeMode.NoResize;

                this.MainApp = ((App)Application.Current); // reference to logging
                this.MainApp.LogMessage("Info","PropertiesWindow Started");                

                this.AppTypeObject = appType;
                this.AppStatus = appStatus;
                this.TreeNodeData = data;

                if (appType == ClassEnumerations.ApplicationType.Class)
                {
                    this.propertyTabs.SelectedTabIndex = 1;
                    this.projectLayoutGroup.IsEnabled = false;

                    if (appStatus == ClassEnumerations.ApplicationStatus.Update)
                    {
                        this.classLayoutGroupHeader.Header = "Update Class Details";

                        // populate textbox details
                        ClassProperties props = (ClassProperties)data.Properties;
                        this.txtBxClassName.Text = props.Name;
                        this.OriginalReportName = this.txtBlkReportname.Text = props.ReportName;
                        this.txtBlkReportPath.Text = props.ReportFolder;
                        this.credentialsUsername.Text = props.Credentials == null? String.Empty:props.Credentials.Username;
                        this.credentialsPassword.Text = props.Credentials == null ? String.Empty : props.Credentials.Password;
                        this.credentialsDomain.Text = props.Credentials == null ? String.Empty : props.Credentials.Domian;
                    }
                    else // new
                    {
                        this.classLayoutGroupHeader.Header = "New Class Details";
                    }
                }
                else // project
                {
                    propertyTabs.SelectedTabIndex = 2;
                    this.classLayoutGroup.IsEnabled = false;
                    if (appStatus == ClassEnumerations.ApplicationStatus.Update)
                    {
                        this.projectLayoutGroupHeader.Header = "Update Project Details";

                        // populate textbox details
                        ProjectProperties props = (ProjectProperties)data.Properties;

                        this.txtProjectName.Text = props.Name;
                        this.serviceUrl.Text = props.ReportWebServiceUrl;
                        this.reportServerUrl.Text = props.ReportServerUrl;
                        this.txtblkSavedPath.Text = props.ProjectSavedPath;
                        this.txtblkCreated.Text = props.ProjectCraeted.ToString();
                        this.radBtnVSTest.IsChecked = props.TestFramework == ClassEnumerations.TestFrameworks.VSTest ? true : false;
                        this.radBtnNUnitTest.IsChecked = props.TestFramework == ClassEnumerations.TestFrameworks.NUnit ? true : false; ;
                        this.radBtnCSharp.IsChecked = props.Language == ClassEnumerations.CodeLanguages.CSharp ? true : false;
                        this.radBtnVB.IsChecked = props.Language == ClassEnumerations.CodeLanguages.VB ? true : false; ;

                        this.testFrameworkPanel.IsEnabled = false;
                    }
                    else // new
                    {
                        this.projectLayoutGroupHeader.Header = "New Project Details";
                        this.txtblkCreated.Text = DateTime.Now.ToString();
                        this.testFrameworkPanel.IsEnabled = true;
                    }
                }
            }
            finally {
                this.MainApp.LogMessage("Info","PropertiesWindow exited"); 
                Mouse.OverrideCursor = null;                
            }
        }

        #region Control Events
        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            try
            {

                this.MainApp.LogMessage("Info","btnCancel_Click entered");
                this.Close();
            }
            finally
            {
                this.MainApp.LogMessage("Info","btnCancel_Click exited");
            }
        }
        private void btnSave_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;

                this.MainApp.LogMessage("Info","btnSave_Click entered");

                // check urls
                if (AppTypeObject == ClassEnumerations.ApplicationType.Project)
                {
                    if (!ValidateUrls())
                    {
                        if (MessageBox.Show("The 'Report Server Url' or the 'Reporting Web Service Url', was not correctly validated. This might be because the server is not contactable or that the urls supplied are incorrect. Do you wish to continue and correct this issue at a later date?", "Possible Invalid Url", MessageBoxButton.OKCancel, MessageBoxImage.Error) == MessageBoxResult.Cancel) return;
                    }

                    if (this.UniqueProjectName())
                    {
                        MessageBox.Show("The project name is not unique within the saved folder path, please assign a unique name to this project.", "Duplicate Project Name", MessageBoxButton.OK, MessageBoxImage.Exclamation);
                        Mouse.OverrideCursor = null;
                        return;
                    }
                }
                else if (AppTypeObject == ClassEnumerations.ApplicationType.Class)
                {
                    if (AppStatus == ClassEnumerations.ApplicationStatus.New)
                    {
                        if (!this.UniqueClassName())
                        {
                            MessageBox.Show("The class name is not unique within this project, please assign a unique name to this class.", "Duplicate Class Name", MessageBoxButton.OK, MessageBoxImage.Exclamation);
                            Mouse.OverrideCursor = null;
                            return;
                        }
                    }                    
                }

                PropsArg propArgs = new PropsArg();
                propArgs.IsUpdated = this.AppStatus == ClassEnumerations.ApplicationStatus.New ? false : true;
                propArgs.AppTypeObject = this.AppTypeObject;

                if (AppTypeObject == ClassEnumerations.ApplicationType.Class)
                {
                    //propArgs.Properties = new ClassProperties();
                    propArgs.Properties = AppStatus == ClassEnumerations.ApplicationStatus.New ? new ClassProperties() : (ClassProperties)this.TreeNodeData.Properties;
                    ((ClassProperties)propArgs.Properties).Name = this.txtBxClassName.Text;
                    ((ClassProperties)propArgs.Properties).ReportName = this.txtBlkReportname.Text;
                    ((ClassProperties)propArgs.Properties).ReportFolder = this.txtBlkReportPath.Text;
                    ((ClassProperties)propArgs.Properties).TreeNodeAssertionDetails = new List<NodeDetails>();
                    ((ClassProperties)propArgs.Properties).Code = String.Empty;

                    // if not all 3 populated - error
                    if (AllCredentialsEntered() == 3)
                    {
                        ((ClassProperties)propArgs.Properties).Credentials = new ReportCredentials() { Domian = this.credentialsDomain.Text, Password = this.credentialsPassword.Text, Username = this.credentialsUsername.Text };
                    }
                    ((ClassProperties)propArgs.Properties).ClassCraeted = DateTime.Now;
                    ((ClassProperties)propArgs.Properties).IsEdited = true;

                    // update nodedetails class name (anyway)
                    if (((ClassProperties)propArgs.Properties).TreeNodeAssertionDetails != null)
                    {
                        for (int loop = 0; loop < ((ClassProperties)propArgs.Properties).TreeNodeAssertionDetails.Count; loop++)
                        {
                            ((ClassProperties)propArgs.Properties).TreeNodeAssertionDetails[loop].ClassName = this.txtBxClassName.Text;
                        }
                    }

                    if (AppStatus == ClassEnumerations.ApplicationStatus.Update)
                    {
                        // check if report name was changed -> now a different report (remove assertions, xml and code)
                        if (this.OriginalReportName.ToLower() != this.txtBlkReportname.Text.ToLower())
                        {
                            if (MessageBox.Show("The report name has changed, if you continue you will lose all your previous assertions, generated code and retrieved xml. Click 'OK' to continue and lose changes.", "Report Change", MessageBoxButton.OKCancel, MessageBoxImage.Exclamation) == MessageBoxResult.Cancel)
                            {
                                Mouse.OverrideCursor = null;
                                return;
                            }
                            else
                            {
                                ((ClassProperties)propArgs.Properties).NumberOfClassTests = 0;
                                ((ClassProperties)propArgs.Properties).Xml = string.Empty;
                                ((ClassProperties)propArgs.Properties).Code = string.Empty;
                                ((ClassProperties)propArgs.Properties).TreeNodeAssertionDetails = new List<NodeDetails>();
                            }
                        }
                    }
                    else // new class
                    {
                        ((ClassProperties)propArgs.Properties).NumberOfClassTests = 0;
                    }
                }
                else // project
                {
                    propArgs.Properties = AppStatus == ClassEnumerations.ApplicationStatus.New ? new ProjectProperties() : (ProjectProperties)this.TreeNodeData.Properties;
                    ((ProjectProperties)propArgs.Properties).Name = this.txtProjectName.Text;
                    if (this.AppStatus == ClassEnumerations.ApplicationStatus.New) ((ProjectProperties)propArgs.Properties).ProjectCraeted = DateTime.Now;
                    ((ProjectProperties)propArgs.Properties).ProjectSavedPath = txtblkSavedPath.Text;
                    ((ProjectProperties)propArgs.Properties).ReportServerUrl = reportServerUrl.Text;
                    ((ProjectProperties)propArgs.Properties).ReportWebServiceUrl = this.serviceUrl.Text;
                    ((ProjectProperties)propArgs.Properties).TestFramework = (bool)this.radBtnVSTest.IsChecked ? ClassEnumerations.TestFrameworks.VSTest : ClassEnumerations.TestFrameworks.NUnit;
                    ((ProjectProperties)propArgs.Properties).Language = (bool)this.radBtnVB.IsChecked ? ClassEnumerations.CodeLanguages.VB : ClassEnumerations.CodeLanguages.CSharp;
                }

                NewPrjPropEvent(this, propArgs);

                this.Close();
            }
            finally
            {
                this.MainApp.LogMessage("Info","btnCancel_Click exited");
            }
        }
        private void btnFolderPath_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                this.MainApp.LogMessage("Info","btnFolderPath_Click entered");

                WPFFolderBrowser.WPFFolderBrowserDialog folderBrowser = new WPFFolderBrowser.WPFFolderBrowserDialog();
                folderBrowser.Title = "Select a folder to save the project to.";

                // System.Reflection.Assembly.GetExecutingAssembly().Location
                folderBrowser.InitialDirectory = Environment.GetLogicalDrives()[0];
                folderBrowser.ShowDialog();

                try // incase use cancelled dialog box
                {
                    this.txtblkSavedPath.Text = folderBrowser.FileName;
                }
                catch (Exception ex) { this.MainApp.LogMessage("Info",ex.Message); };
            }
            finally
            {
                this.MainApp.LogMessage("Info","btnFolderPath_Click exited");
            }
        }
        private int  AllCredentialsEntered()
        {
            try
            {
                this.MainApp.LogMessage("Info","AllCredentialsEntered Entered");

                int count = 0; // count has to be zero or three - not in between

                if (!String.IsNullOrEmpty(this.credentialsDomain.Text)) count++;
                if (!String.IsNullOrEmpty(this.credentialsPassword.Text)) count++;
                if (!String.IsNullOrEmpty(this.credentialsUsername.Text)) count++;                

                return count;
            }
            finally
            {
                this.MainApp.LogMessage("Info","AllCredentialsEntered exited");
            }
        }
        #endregion

        #region Class Methods - Private
        private void ValidateContents(object sender, RoutedEventArgs e)
        {
            this.MainApp.LogMessage("Info","ValidateContents entered");

            bool state = false;
            if (AppTypeObject == ClassEnumerations.ApplicationType.Class)
            {
                if (!String.IsNullOrEmpty(this.txtBxClassName.Text) && !String.IsNullOrEmpty(txtBlkReportname.Text)) state = true;
            }
            else
            {
                if (!String.IsNullOrEmpty(this.txtProjectName.Text) && !String.IsNullOrEmpty(serviceUrl.Text) && !String.IsNullOrEmpty(reportServerUrl.Text) && !String.IsNullOrEmpty(txtblkSavedPath.Text)) state = true;
                // state = ValidateUrls();
            }

            this.btnSave.IsEnabled = state;

            this.MainApp.LogMessage("Info","ValidateContents exited");
        }
        private bool ValidateUrls()
        {
            try
            {
                this.MainApp.LogMessage("Info","ValidateUrls entered");

                // test urls with lost focus instead of selection changed (as it is validated with eacg key stroke)
                ValidateWebSerivce validate = new ValidateWebSerivce();

                if (!String.IsNullOrEmpty(this.serviceUrl.Text))
                {
                    string errorMessage = string.Empty;
                    if (!validate.ServiceExists(this.serviceUrl.Text, false, out errorMessage))
                    {
                        this.MainApp.LogMessage("Info",errorMessage); // log error message

                        this.NotifyedUser(this, new NotificationArgs() { Message = errorMessage, ImagePath = "/Images/16x16-Errors.png" });
                        return false;
                    }
                }

                if (!String.IsNullOrEmpty(this.reportServerUrl.Text))
                {
                    string errorMessage = string.Empty;
                    if (!validate.ServiceExists(this.reportServerUrl.Text, false, out errorMessage))
                    {
                        this.NotifyedUser(this, new NotificationArgs() { Message = errorMessage, ImagePath = "/Images/16x16-Errors.png" });
                        return false;
                    }
                }
                return true;
            }
            finally
            {
                this.MainApp.LogMessage("Info","ValidateUrls exited");
            }
        }
        private bool UniqueProjectName()
        {
            try
            {
                this.MainApp.LogMessage("Info","UniqueProjectName entered");
                return File.Exists(this.txtblkSavedPath.Text + @"\" + this.txtProjectName.Text + ".rst");
            }
            finally
            {
                this.MainApp.LogMessage("Info","UniqueProjectName exited");
            }
        }
        private bool UniqueClassName()
        {
            try
            {
                this.MainApp.LogMessage("Info","UniqueClassName entered");

                return this.CheckedDoesClassNameExist(this, this.txtBxClassName.Text);
            }
            finally
            {
                this.MainApp.LogMessage("Info","UniqueClassName exited");
            }
        }
        #endregion
    }
}
